package com.lx.seckill.controller;

import com.lx.seckill.pojo.TSeckillProduct;
import com.lx.seckill.service.TseckillProductService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

/**
 * TODO 添加描述
 *
 * @author wangLJ
 * @date 2024/7/18 11:33
 */
@RestController
@RequestMapping("/sec")
public class SeckillContoller {

    public Integer count =0;
    @Autowired
    private TseckillProductService service;

    @Autowired
    private ThreadPoolTaskExecutor executor;


    @GetMapping("/list")
    public List<TSeckillProduct> getList(){
        List<TSeckillProduct> list = service.list();

        System.out.println(count);
        return list;
    }


    @GetMapping("/byid")
    public  TSeckillProduct  byid(){
         TSeckillProduct  list = service.byid();


        return list;
    }

    @GetMapping("/kill")
    public String kill()  {
        /**
         * 原因在于，有很多线程同时执行了service.byid();方法
         * 拿到的库存，保存在自己的栈帧中。如果有一百个线程拿到的库存是大于0的，就有一百个线程去执行扣库存的方法
         */
        TSeckillProduct  list = service.byid();

        //同样也会有多个线程进入这个 ,比如两个线程库存都是1
        if (list.getStockCount()>0){
            //扣减库存
            service.updateStockCount();
        }

        return "ok";
    }


    /**
     * 使用分布式锁实现秒杀
     * @return
     */


    @GetMapping("/redissonkill")
    public String redissonkill()  {



        TSeckillProduct  list = service.byid();

        //同样也会有多个线程进入这个 ,比如两个线程库存都是1
        if (list.getStockCount()>0){
            //扣减库存
            service.updateStockCount();
        }

        return "ok";
    }


    /**
     * Callable<String>异步处理测试
     * @return
     */
    @RequestMapping("/async")
    @ResponseBody
    public Callable<String> callable() {
        // 这么做的好处避免web server的连接池被长期占用而引起性能问题，
        // 调用后生成一个非web的服务线程来处理，增加web服务器的吞吐量。

        return new Callable<String>() {
            @Override
            public String call() throws Exception {

                String threadName = Thread.currentThread().getName();
                System.out.println("小单 - " +threadName);
                return "小单 - " +threadName+ System.currentTimeMillis();
            }
        };

    }


    /**
     *  异步请求 CompletableFuture<String>
     * @return
     */
    @GetMapping("/asynd")
    @Async("threadPoolTaskExecutor") // 指定使用哪个TaskExecutor
    public CompletableFuture<String> handleAsyncRequest() {
        return CompletableFuture.supplyAsync(() -> {
            String threadName = Thread.currentThread().getName();
            System.out.println("阿里 - " +threadName);
            // 模拟一个耗时操作
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("Sleep interrupted", e);
            }
            return "Hello from async method!";
        }, executor);
    }

    /**
     * 自定义线程池异步处理  CompletableFuture<TSeckillProduct>
     * @return
     */
    @RequestMapping("/asynList")
    @ResponseBody
    @Async("threadPoolTaskExecutor") // 指定使用哪个TaskExecutor
    public CompletableFuture<TSeckillProduct>  asynList() {
        // 这么做的好处避免web server的连接池被长期占用而引起性能问题，
        // 调用后生成一个非web的服务线程来处理，增加web服务器的吞吐量。
        return CompletableFuture.supplyAsync(() -> {
            String threadName = Thread.currentThread().getName();
            System.out.println("阿里 - " +threadName);
            // 模拟一个耗时操作
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("Sleep interrupted", e);
            }
            return    service.byid();
        }, executor);

    }

    /**
     * 初始化库存
     * @return
     */
    @RequestMapping("/putIfAbsent")
    @ResponseBody
    public String  putIfAbsent() {
        return service.putIfAbsent();

    }


    /**
     * 库存预热-秒杀 increment
     * @return
     */
    @RequestMapping("/preheat")
    @ResponseBody
    public String  preheat() {
       return service.preheat();

    }


    /**
     * 异步秒杀  increment
     * @return
     */
    @RequestMapping("/asynPreheat")
    @ResponseBody
    public CompletableFuture<String>  asynPreheat() {

        return service.asynPreheat();

    }











    @GetMapping("/kills")
    public String kills()  {


//        try {
//            Thread.sleep(100);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }

        TSeckillProduct  list = service.byid();

        if (list.getStockCount()>0){
            //扣减库存
            service.updateStockCount();
        }
        String uuid = UUID.randomUUID().toString();

        String threadName = Thread.currentThread().getName();
        count++ ;
        if (count==50){
            System.out.println(threadName+ "  " + count);
        }
        String s ="当前线程的名称"+ threadName + " UUDI" +  uuid + "时间" +  System.currentTimeMillis() +  " "+ count;
        return s;
    }

}
